--util

local string, sjson, pairs, wifi, tonumber = string, sjson, pairs, wifi, tonumber
local file, type, table, print, rtctime = file, type, table, print, rtctime
local pcall, _G = pcall, _G
local Args = {}
local _sck = nil

module('util')

--send
local function send(sck, result)    
    local ok, result_t = pcall(sjson.encode, result)
    if (ok) then
        local response = 'HTTP/1.1 200 OK\r\n'
                    ..'Content-Type: application/json\r\n'
                    ..'Connection: close\r\n'
                    ..'Transfer-Encoding: chunked\r\n'
                    ..'\r\n'
                    ..("%X\r\n"):format(#result_t)
                    ..result_t..'\r\n'
                    ..'0\r\n'
                    ..'\r\n'
        sck:send(response, sender)
        print('\n'..response)
        local function sender()
            sck:close()
            result_t =nil
            response = nil
        end        
    else
        sck:close()
    end --outer if
end

--read wifi
function read_wifi()
local config_cache = wifi.sta.getapinfo()
    if (type(config_cache) == 'table') then
        config_cache['cmd'] = 'read_wifi'
        config_cache['success'] = true
        config_cache['index_of_ap'] = wifi.sta.getapindex()
    else
        config_cache = {}
        config_cache['cmd'] = 'read_wifi'
        config_cache['success'] = false
    end
    return config_cache
end
--read config
function read_config(f, default)
    local result = default
    if (file.open(f..'.lua')) then
        local line = file.readline()
        file.close()        
        local ok, json = pcall(sjson.decode, line)
        if (ok) then
            result = json
        end                           
    end
    return result
end

--write config
local function write_config(f, data)
    local ok = false
    if (file.open(f..'.lua', 'w+')) then
        if (type(data) == 'string') then
            if (file.write(data)) then
                ok = true
            end
        end
        file.close()
    end
    return {success=ok}
end

--callback: scan ap
local function cb_listap(t)
    local result_t = {cmd='list_ap'}
    for k, v in pairs(t) do
        local ssid, rssi, _, _ = string.match(v, "([%w%-_]+),([^,]+),([^,]+),([^,]*)")
        if (ssid ~= nil and tonumber(rssi) > -90) then
            table.insert(result_t, ssid..','..rssi)
        end
    end
    send(_sck, result_t)
end

--parse header
function parse(sck, data)
    local result = nil
    local post_data = string.match(data, '{.+}')
    if post_data ~= nil then
        local Args = sjson.decode(post_data)
        --t&h
        if (Args.cmd=='read_th' and not _G._busy) then
            result = {temp=_G._t, hum=_G._rh, time=_G._timestamp, type=_G._type, cmd='read_th', success=true}
        else
            result = {cmd='read_th', success=false} 
        end
        --read wifi
        if (Args.cmd == 'read_wifi') then
            result = read_wifi()
        end
        --scan wifi
        if (Args.cmd == 'list_ap') then
            _sck = sck
            wifi.sta.getap(1, cb_listap)
        end
        --write wifi
        if (Args.cmd == 'write_wifi') then
            local cfg = {}
            cfg.ssid = Args.ssid
            cfg.pwd = Args.password
            cfg.save = true
            cfg.auto = true
            local ok = wifi.sta.config(cfg)
            result = {cmd='write_wifi', success=ok}
        end
        --read device
        if (Args.cmd == 'read_device') then
            result = read_config('device', _G._device)
            result.cmd = 'read_device'
        end
        --write device
        if (Args.cmd == 'write_device') then
            result = write_config('device', Args.data)
            result.cmd = 'write_device'
        end
        --ddns
        if (Args.cmd == 'read_ddns') then
            result = read_config('ddns', {host='demo',domain='ns360.info',user='',password=''})
            result.cmd = 'read_ddns'
        end
        if (Args.cmd == 'write_ddns') then
            result = write_config('ddns', Args.data)
            result.cmd = 'write_ddns'
            result.success = false;
            local ok, ddns = pcall(sjson.decode, Args.data)
            if (ok) then
                _G._ddns = ddns
                result.success = true
            end
        end
        --write network
        if (Args.cmd == 'write_network') then
            result = write_config('network', Args.data)
            result.cmd = 'write_network'
        end
        --read all
        if (Args.cmd == 'read_all') then
            local w = read_wifi()            
            local d = read_config('device', _G._device)
            local n = read_config('network', _G._network)
            n['mac'] = wifi.sta.getmac()
            result = {wifi=w, device=d, network=n, cmd='read_all', success=true}
        end
        --hello
        if (Args.cmd == 'say_hello') then
            result = {mac=wifi.sta.getmac(), success=true, cmd='say_hello'}
        end
        --set time
        if (Args.cmd == 'set_time') then
            rtctime.set(tonumber(Args.data), 0)
            result = {cmd='set_time', success=true}
        end
        --at the end, send
        send(sck, result)
    --outer if
    end
end
